package com.foryou.swkj.core.util;

import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Created by Dante Fung on 2017/7/18.
 */
public class DateTimeUtils
{
    public static final String PATTERN_DEFAULT = "yyyy-MM-dd";
    public static final String PATTERN_DAYPATH = "yyyy\\MM\\dd\\";
    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATETIME_COMPACT = "yyyyMMddHHmmss";
    public static final String PATTERN_DATE_COMPACT = "yyyyMMdd";
    public static final String PATTERN_DATESHORT = "yyMMdd";
    public static final String PATTERN_YEARMONTH = "yyyyMM";

    public static String formatDate(Date date)
    {
        if (date == null)
            return null;
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    public static String formatDate(Date date, String pattern)
    {
        return new SimpleDateFormat(pattern).format(date);
    }

    public static Date parseDate(String dateString, String pattern)
    {
        try
        {
            return new SimpleDateFormat(pattern).parse(dateString); } catch (ParseException pe) {
        }
        return null;
    }

    public static Date parseDate(String dateString)
    {
        return parseDate(dateString, "yyyy-MM-dd");
    }

    public static Date accountDate(Date date, int timeUnit, int amount)
    {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(timeUnit, amount);
        return c.getTime();
    }

    public static int getDaysOfCurrentYear(Date date)
    {
        Calendar c = GregorianCalendar.getInstance();
        c.setTime(date);
        return c.isLenient() ? 366 : 365;
    }

    public static int getDaysOfCurrentMonth(Date date)
    {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getActualMaximum(5);
    }

    public static int getWeekOfCurrentDate(Date date)
    {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(3) - 1;
    }

    public static int getDiscrepantUnits(Date date1, Date date2, int timeUnit)
    {
        if (isSameDate(date1, date2))
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(date1.before(date2) ? date1 : date2);
        c2.setTime(date1.before(date2) ? date2 : date1);
        int count = -1;
        while (c1.before(c2)) {
            c1.add(timeUnit, 1);
            count++;
        }

        return date1.before(date2) ? count : -count;
    }

    public static int getDiscrepantDays(Date dateStart, Date dateEnd)
    {
        return (int)((dateEnd.getTime() - dateStart.getTime()) / 1000L / 60L / 60L / 24L);
    }

    public static int getDiscrepantMonthI(Date dateStart, Date dateEnd)
    {
        Calendar calendarEnd = Calendar.getInstance();
        Calendar calendarStart = Calendar.getInstance();
        calendarEnd.setTime(dateEnd);
        calendarStart.setTime(dateStart);
        return (calendarEnd.get(1) - calendarStart.get(1)) * 12 + (calendarEnd.get(2) - calendarStart.get(2));
    }

    public static int getDiscrepantWeeks(Date dateStart, Date dateEnd)
    {
        Calendar calendarEnd = Calendar.getInstance();
        Calendar calendarStart = Calendar.getInstance();
        calendarEnd.setTime(dateEnd);
        calendarStart.setTime(dateStart);
        return calendarEnd.get(3) - calendarStart.get(3);
    }

    public static int compareDay(Date d1, Date d2)
    {
        return d1.before(d2) ? -1 : isSameDay(d1, d2) ? 0 : 1;
    }

    public static boolean isSameDate(Date date1, Date date2)
    {
        return (!date1.before(date2)) && (!date2.before(date1));
    }

    public static boolean isSameDay(Date date1, Date date2)
    {
        return formatDate(date1).equals(formatDate(date2));
    }

    public static Date getStartOfDay(Date date)
    {
        return parseDate(formatDate(date, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getEndOfDay(Date date)
    {
        return parseDate(formatDate(date, "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getEndOfYear(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return parseDate(calendar.get(1) + "-12-31");
    }

    public static Date getStartOfYear(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return parseDate(calendar.get(1) + "-01-01");
    }

    public static Date getEndOfNextMonth(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, 1);
        calendar.set(5, getDaysOfCurrentMonth(parseDate(calendar.get(1) + "-" + (calendar.get(2) + 1) + "-1")));

        return calendar.getTime();
    }

    public static Date getStartOfWeek(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(7) - 1;
        calendar.add(5, -dayOfWeek);
        return getStartOfDay(calendar.getTime());
    }

    public static Date getEndOfWeek(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(7) - 1;
        calendar.add(5, 6 - dayOfWeek);
        return getEndOfDay(calendar.getTime());
    }

    public static Date getStartOfMonth(Date date)
    {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(1);
        int month = calendar.get(2) + 1;
        int day = 1;
        return getStartOfDay(parseDate(String.valueOf(year) + "-" + String.valueOf(month) + "-" + String.valueOf(day)));
    }

    public static Date getEndOfMonth(Date date)
    {
        date = getStartOfMonth(date);
        date = accountDate(date, 2, 1);
        date = accountDate(date, 5, -1);
        return getEndOfDay(date);
    }

    public static Date[] parseDateRange(String dateRange, String format)
    {
        if (StringUtils.isEmpty(dateRange)) {
            return new Date[] { null, null };
        }
        String[] dates = dateRange.split("-");
        return new Date[] { parseDate(dates[0].trim(), format), parseDate(dates[1].trim(), format) };
    }

    public static String formatDateRange(Date stime, Date etime, String format)
    {
        if ((stime != null) && (etime != null)) {
            return formatDate(stime, format) + " - " + formatDate(etime, format);
        }

        return "";
    }

    private static int getMondayPlus()
    {
        Calendar cd = Calendar.getInstance();

        int dayOfWeek = cd.get(7);
        if (dayOfWeek == 1) {
            return -6;
        }
        return 2 - dayOfWeek;
    }

    public static String getSuchMonday(int weeks)
    {
        int mondayPlus = getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(5, mondayPlus + 7 * weeks);
        Date monday = currentDate.getTime();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        StringBuffer str = new StringBuffer(df.format(monday));
        str.append(" 00:00:00");
        return str.toString();
    }

    public static String getSuchSunday(int weeks)
    {
        int mondayPlus = getMondayPlus();
        GregorianCalendar currentDate = new GregorianCalendar();
        currentDate.add(5, mondayPlus + 7 * weeks + 6);
        Date monday = currentDate.getTime();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        StringBuffer str = new StringBuffer(df.format(monday));
        str.append(" 23:59:59");
        return str.toString();
    }

    public static String getDayStartString(Date time)
    {
        Date day = time;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        StringBuffer str = new StringBuffer(df.format(day));
        return str.toString();
    }

    public static Date getDayStart(Date time)
    {
        String timeStr = getDayStartString(time);
        time = stringToTime(timeStr);
        return time;
    }

    public static String getDayEndString(Date time)
    {
        Date day = time;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
        StringBuffer str = new StringBuffer(df.format(day));
        return str.toString();
    }

    public static Date getDayEnd(Date time)
    {
        String timeStr = getDayEndString(time);
        time = stringToTime(timeStr);
        return time;
    }

    public static Date stringToTime(String str)
    {
        Date time = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            time = df.parse(str.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return time;
    }

    public static Date stringToTimeOnlyDate(String str)
    {
        Date time = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            time = df.parse(str.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return time;
    }

    public static Date stringToTimeOnlyTime(String str)
    {
        Date time = new Date();
        DateFormat df = new SimpleDateFormat("HH:mm:ss");
        try {
            time = df.parse(str.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return time;
    }

    public static Date stringToTimeOnlyTimeNoneSecond(String str)
    {
        Date time = new Date();
        DateFormat df = new SimpleDateFormat("HH:mm");
        try {
            time = df.parse(str.toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return time;
    }

    public static String timeToString(Date time)
    {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(time);
    }

    public static String timeToString(Date time, String format)
    {
        DateFormat df = new SimpleDateFormat(format);
        return df.format(time);
    }

    public static String timeToStringOnlyDate(Date time)
    {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(time);
    }

    public static String timeToString2(Date time)
    {
        DateFormat df = new SimpleDateFormat("MM/dd");
        return df.format(time);
    }

    public static Date getCurrentTime()
    {
        return getCurrentCalendar().getTime();
    }

    public static Date getCurrentDate()
    {
        Calendar result = getCurrentCalendar();
        result.set(10, 0);
        result.set(12, 0);
        result.set(13, 0);
        return result.getTime();
    }

    public static Date timeToTimeOnlyDate(Date time)
    {
        String str = timeToStringOnlyDate(time);
        time = stringToTimeOnlyDate(str);
        return time;
    }

    private static Calendar getCurrentCalendar()
    {
        return Calendar.getInstance();
    }

    public static int getWeeksByYear(int year)
    {
        Calendar c = Calendar.getInstance();

        if (year == 0) {
            year = c.get(1);
        }

        c.set(1, year + 1);

        c.set(2, 1);

        c.set(6, 1);

        c.add(6, -7);

        return c.get(3);
    }

    public static int getQuarter(int month)
    {
        return month / 4 + 1;
    }
}